home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / ka9q / nhclb120.zoo / mbuf.c < prev    next >
C/C++ Source or Header  |  1992-08-19  |  9KB  |  462 lines

  1. /* Primitive mbuf allocate/free routines */
  2.  
  3. #include "global.h"
  4. #include "mbuf.h"
  5. #ifdef    UNIX
  6. #include <memory.h>
  7. #endif
  8.  
  9. /* Allocate mbuf with associated buffer of 'size' bytes */
  10. struct mbuf *
  11. alloc_mbuf(int16 size)
  12. #ifndef __STDC__
  13. register int16 size;
  14. #endif
  15. {
  16.     register struct mbuf *bp;
  17.  
  18.     if((bp = (struct mbuf *)malloc((unsigned)(size + sizeof(struct mbuf)))) == NULLBUF)
  19.         return NULLBUF;
  20.     bp->next = bp->anext = NULLBUF;
  21.     if(size != 0){
  22.         bp->data = (char *)(bp + 1);
  23.     } else {
  24.         bp->data = NULLCHAR;
  25.     }
  26.     bp->size = size;
  27.     bp->cnt = 0;
  28.     return bp;
  29. }
  30.  
  31. /* Free all resources associated with mbuf
  32.  * Return pointer to next mbuf in packet chain
  33.  */
  34. struct mbuf *
  35. free_mbuf(bp)
  36. register struct mbuf *bp;
  37. {
  38.     register struct mbuf *bp1 = NULLBUF;
  39.  
  40.     if(bp != NULLBUF){
  41.         bp1 = bp->next;
  42.         bp->next = NULLBUF;    /* detect attempts to use */
  43.         bp->data = NULLCHAR;    /* a freed mbuf */
  44.         free((char *)bp);
  45.     }
  46.     return bp1;
  47. }
  48.  
  49. /* Free packet (a chain of mbufs). Return pointer to next packet on queue,
  50.  * if any
  51.  */
  52. struct mbuf *
  53. free_p(bp)
  54. register struct mbuf *bp;
  55. {
  56.     struct mbuf *abp;
  57.  
  58.     if(bp == NULLBUF)
  59.         return NULLBUF;
  60.     abp = bp->anext;
  61.     while(bp != NULLBUF)
  62.         bp = free_mbuf(bp);
  63.     return abp;
  64. }        
  65. /* Free entire queue of packets (of mbufs) */
  66. free_q(q)
  67. struct mbuf **q;
  68. {
  69.     register struct mbuf *bp;
  70.  
  71.     while((bp = dequeue(q)) != NULLBUF)
  72.         free_p(bp);
  73. }
  74.  
  75. /* Count up the total number of bytes in an mbuf */
  76. int16
  77. len_mbuf(bp)
  78. register struct mbuf *bp;
  79. {
  80.     int cnt;
  81.  
  82.     cnt = 0;
  83.     while(bp != NULLBUF){
  84.         cnt += bp->cnt;
  85.         bp = bp->next;
  86.     }
  87.     return cnt;
  88. }
  89. /* Count up the number of packets in a queue */
  90. int16
  91. len_q(bp)
  92. register struct mbuf *bp;
  93. {
  94.     register int cnt;
  95.  
  96.     for(cnt=0;bp != NULLBUF;cnt++,bp = bp->anext)
  97.         ;
  98.     return cnt;
  99. }
  100. /* Trim mbuf to specified length by lopping off end */
  101. trim_mbuf(bpp,length)
  102. struct mbuf **bpp;
  103. int16 length;
  104. {
  105.     register int16 tot = 0;
  106.     register struct mbuf *bp;
  107.  
  108.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  109.         return;    /* Nothing to trim */
  110.  
  111.     if(length == 0){
  112.         /* Toss the whole thing */
  113.         free_p(*bpp);
  114.         *bpp = NULLBUF;
  115.         return;
  116.     }
  117.     /* Find the point at which to trim. If length is greater than
  118.      * the packet, we'll just fall through without doing anything
  119.      */
  120.     for( bp = *bpp; bp != NULLBUF; bp = bp->next){
  121.         if(tot + bp->cnt < length){
  122.             tot += bp->cnt;
  123.         } else {
  124.             /* Cut here */
  125.             bp->cnt = length - tot;
  126.             free_p(bp->next);
  127.             bp->next = NULLBUF;
  128.             break;
  129.         }
  130.     }
  131. }
  132. /* Duplicate/enqueue/dequeue operations based on mbufs */
  133.  
  134. /* Duplicate first 'cnt' bytes of packet starting at 'offset'.
  135.  * This is done without copying data; only the headers are duplicated,
  136.  * but without data segments of their own. The pointers are set up to
  137.  * share the data segments of the original copy. The return pointer is
  138.  * passed back through the first argument, and the return value is the
  139.  * number of bytes actually duplicated.
  140.  */
  141. int16
  142. dup_p(MBUF ** hp,MBUF *bp,int16 offset,int16 cnt)
  143. #ifndef __STDC__
  144. struct mbuf **hp;
  145. register struct mbuf *bp;
  146. register int16 offset;
  147. register int16 cnt;
  148. #endif
  149. {
  150.     register struct mbuf *cp;
  151.     int16 tot;
  152.  
  153.     if(cnt == 0 || bp == NULLBUF || hp == NULLBUFP){
  154.         if(hp != NULLBUFP)
  155.             *hp = NULLBUF;
  156.         return 0;
  157.     }
  158.     if((*hp = cp = alloc_mbuf(0)) == NULLBUF){
  159.         return 0;
  160.     }
  161.     /* Skip over leading mbufs that are smaller than the offset */
  162.     while(bp != NULLBUF && bp->cnt <= offset){
  163.         offset -= bp->cnt;
  164.         bp = bp->next;
  165.     }
  166.     if(bp == NULLBUF){
  167.         free_mbuf(cp);
  168.         *hp = NULLBUF;
  169.         return 0;    /* Offset was too big */
  170.     }
  171.     tot = 0;
  172.     for(;;){
  173.         cp->data = bp->data + offset;
  174.         cp->cnt = min(cnt,bp->cnt - offset);
  175.         offset = 0;
  176.         cnt -= cp->cnt;
  177.         tot += cp->cnt;
  178.         bp = bp->next;
  179.         if(cnt == 0 || bp == NULLBUF || (cp->next = alloc_mbuf(0)) == NULLBUF)
  180.             break;
  181.         cp = cp->next;
  182.     }
  183.     return tot;
  184. }
  185. /* Copy first 'cnt' bytes of packet into a new, single mbuf */
  186. struct mbuf *
  187. copy_p(MBUF *bp,int16 cnt)
  188. #ifndef __STDC__
  189. register struct mbuf *bp;
  190. register int16 cnt;
  191. #endif
  192. {
  193.     register struct mbuf *cp;
  194.     register char *wp;
  195.     register int16 n;
  196.  
  197.     if(bp == NULLBUF || cnt == 0 || (cp = alloc_mbuf(cnt)) == NULLBUF)
  198.         return NULLBUF;
  199.     wp = cp->data;
  200.     while(cnt != 0 && bp != NULLBUF){
  201.         n = min(cnt,bp->cnt);
  202.         memcpy(wp,bp->data,(int)n);
  203.         wp += n;
  204.         cp->cnt += n;
  205.         cnt -= n;
  206.         bp = bp->next;
  207.     }
  208.     return cp;
  209. }
  210. /* Copy and delete "cnt" bytes from beginning of packet. Return number of
  211.  * bytes actually pulled off
  212.  */
  213. int16
  214. pullup(MBUF **bph,char *buf,int16 cnt)
  215. #ifndef __STDC__
  216. struct mbuf **bph;
  217. char *buf;
  218. int16 cnt;
  219. #endif
  220. {
  221.     register struct mbuf *bp;
  222.     int16 n,tot;
  223.  
  224.     tot = 0;
  225.     if(bph == NULLBUFP)
  226.         return 0;
  227.     while(*bph != NULLBUF && cnt != 0){
  228.         bp = *bph;
  229.         n = min(cnt,bp->cnt);
  230.         if(buf != NULLCHAR && n != 0){
  231.             memcpy(buf,bp->data,(int)n);
  232.             buf += n;
  233.         }
  234.         tot += n;
  235.         cnt -= n;
  236.         bp->data += n;
  237.         bp->cnt -= n;        
  238.         if(bp->cnt == 0){
  239.             *bph = free_mbuf(bp);
  240.         }
  241.     }
  242.     return tot;
  243. }
  244. /* Append mbuf to end of mbuf chain */
  245. void
  246. append(bph,bp)
  247. struct mbuf **bph;
  248. struct mbuf *bp;
  249. {
  250.     register struct mbuf *p;
  251.  
  252.     if(bph == NULLBUFP || bp == NULLBUF)
  253.         return;
  254.     if(*bph == NULLBUF){
  255.         /* First one on chain */
  256.         *bph = bp;
  257.     } else {
  258.         for(p = *bph ; p->next != NULLBUF ; p = p->next)
  259.             ;
  260.         p->next = bp;
  261.     }
  262. }
  263. /* Insert specified amount of contiguous new space at the beginning of an
  264.  * mbuf chain. If enough space is available in the first mbuf, no new space
  265.  * is allocated. Otherwise a mbuf of the appropriate size is allocated and
  266.  * tacked on the front of the chain.
  267.  *
  268.  * This operation is the logical inverse of pullup(), hence the name.
  269.  */
  270. struct mbuf *
  271. pushdown(MBUF *bp,int16 size)
  272. #ifndef __STDC__
  273. register struct mbuf *bp;
  274. int16 size;
  275. #endif
  276. {
  277.     register struct mbuf *nbp;
  278.  
  279.     /* Check that bp is real and that there's data space associated with
  280.      * this buffer (i.e., this is not a buffer from dup_p) before
  281.      * checking to see if there's enough space at its front
  282.      */
  283.     if(bp != NULLBUF && bp->size != 0 && bp->data - (char *)(bp+1) >= size){
  284.         /* No need to alloc new mbuf, just adjust this one */
  285.         bp->data -= size;
  286.         bp->cnt += size;
  287.     } else {
  288.         if((nbp = alloc_mbuf(size)) != NULLBUF){
  289.             nbp->next = bp;
  290.             nbp->cnt = size;
  291.             bp = nbp;
  292.         } else {
  293.             bp = NULLBUF;
  294.         }
  295.     }
  296.     return bp;
  297. }
  298. /* Append packet to end of packet queue */
  299. void
  300. enqueue(q,bp)
  301. struct mbuf **q;
  302. struct mbuf *bp;
  303. {
  304.     register struct mbuf *p;
  305.     char i_state;
  306.  
  307.     if(q == NULLBUFP || bp == NULLBUF)
  308.         return;
  309.     i_state = disable();
  310.     if(*q == NULLBUF){
  311.         /* List is empty, stick at front */
  312.         *q = bp;
  313.     } else {
  314.         for(p = *q ; p->anext != NULLBUF ; p = p->anext)
  315.             ;
  316.         p->anext = bp;
  317.     }
  318.     restore(i_state);
  319. }
  320. /* Unlink a packet from the head of the queue */
  321. struct mbuf *
  322. dequeue(q)
  323. register struct mbuf **q;
  324. {
  325.     register struct mbuf *bp;
  326.     char i_state;
  327.  
  328.     if(q == NULLBUFP)
  329.         return NULLBUF;
  330.     i_state = disable();
  331.     if((bp = *q) != NULLBUF){
  332.         *q = bp->anext;
  333.         bp->anext = NULLBUF;
  334.     }
  335.     restore(i_state);
  336.     return bp;
  337. }    
  338.  
  339. /* Copy user data into an mbuf */
  340. struct mbuf *
  341. qdata(char *data,int16 cnt)
  342. #ifndef __STDC__
  343. char *data;
  344. int16 cnt;
  345. #endif
  346. {
  347.     register struct mbuf *bp;
  348.  
  349.     if((bp = alloc_mbuf(cnt)) == NULLBUF)
  350.         return NULLBUF;
  351.     memcpy(bp->data,data,(int)cnt);
  352.     bp->cnt = cnt;
  353.     return bp;
  354. }
  355. /* Copy mbuf data into user buffer */
  356. int16
  357. dqdata(bp,buf,cnt)
  358. struct mbuf *bp;
  359. char *buf;
  360. unsigned cnt;
  361. {
  362.     unsigned n,tot;
  363.     struct mbuf *bp1;
  364.  
  365.     if(buf == NULLCHAR)
  366.         return 0;
  367.     
  368.     tot = 0;
  369.     for(bp1 = bp;bp1 != NULLBUF; bp1 = bp1->next){
  370.         n = min(bp1->cnt,cnt);
  371.         memcpy(buf,bp1->data,(int)n);
  372.         cnt -= n;
  373.         buf += n;
  374.         tot += n;
  375.     }
  376.     free_p(bp);
  377.     return tot;
  378. }
  379. /* Pull a 32-bit integer in host order from buffer in network byte order */
  380. int32
  381. pull32(bpp)
  382. struct mbuf **bpp;
  383. {
  384.     int32 rval;
  385.     char buf[4];
  386.     register char *cp;
  387.  
  388.     if(pullup(bpp,buf,4) != 4){
  389.         /* Return zero if insufficient buffer */
  390.         return 0;
  391.     }
  392.     cp = buf;
  393.  
  394.     /* Unwound for speed */
  395.     rval = uchar(*cp++);
  396.     rval <<= 8;
  397.     rval |= uchar(*cp++);
  398.     rval <<= 8;
  399.     rval |= uchar(*cp++);
  400.     rval <<= 8;
  401.     rval |= uchar(*cp);
  402.  
  403.     return rval;
  404. }
  405. /* Pull a 16-bit integer in host order from buffer in network byte order */
  406. int16
  407. pull16(bpp)
  408. struct mbuf **bpp;
  409. {
  410.     int16 rval;
  411.     char buf[2];
  412.     register char *cp;
  413.  
  414.     if(pullup(bpp,buf,2) != 2){
  415.         /* Return zero if insufficient buffer */
  416.         return 0;
  417.     }
  418.     cp = buf;
  419.  
  420.     rval = uchar(*